package com.wf.netty.bytebuf;

import io.netty.buffer.*;
import org.junit.jupiter.api.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.nio.charset.StandardCharsets;

/**
 * 功能描述
 *
 * @author wf
 * @since 2022/5/24
 */
public class MyByteBuf {
    private static final Logger LOGGER = LoggerFactory.getLogger(MyByteBuf.class);

    @Test
    public void testRefCount() {
        ByteBuf buffer  = ByteBufAllocator.DEFAULT.buffer();
        LOGGER.info("after create ref is: {}", buffer.refCnt());

        buffer.retain();
        LOGGER.info("first retain ref is: {}", buffer.refCnt());

        buffer.release();
        LOGGER.info("first release ref is: {}", buffer.refCnt());

        buffer.release();
        LOGGER.info("second release ref is: {}", buffer.refCnt());

        // IllegalReferenceCountException 引用计数为0的缓冲区不能再继续使用,
        // 开发中retain()和release()方法应该结对使用
        buffer.retain();
    }

    @Test
    public void testByteBufAllocator() {
        ByteBuf buffer = null;

        // 通过默认分配器分配初始容量为9、最大容量为100的缓冲区
        buffer = ByteBufAllocator.DEFAULT.buffer(9, 100);

        // 初始容量为256、最大容量为Integer.MAX_VALUE的缓冲区
        buffer = ByteBufAllocator.DEFAULT.buffer();

        //非池化分配器，分配Java的堆（Heap）结构内存缓冲区
        buffer = UnpooledByteBufAllocator.DEFAULT.heapBuffer();

        //池化分配器，分配由操作系统管理的直接内存缓冲区
        buffer = PooledByteBufAllocator.DEFAULT.directBuffer();
    }

    @Test
    public void testHeapBuffer() {
        ByteBuf heapBuffer = ByteBufAllocator.DEFAULT.heapBuffer();
        heapBuffer.writeBytes("hello world heapBuffer".getBytes(StandardCharsets.UTF_8));

        // 堆内存能取到内部数组
        if (heapBuffer.hasArray()) {
            byte[] array = heapBuffer.array();
            int offset = heapBuffer.arrayOffset() + heapBuffer.readerIndex();
            int length = heapBuffer.readableBytes();

            // byte数组转string
            LOGGER.info(new String(array, offset, length, StandardCharsets.UTF_8));
        }
        // 释放
        heapBuffer.release();
    }

    @Test
    public void testDirectBuffer() {
        ByteBuf directBuf=  ByteBufAllocator.DEFAULT.directBuffer();
        directBuf.writeBytes("hello world directBuf".getBytes(StandardCharsets.UTF_8));
        if (!directBuf.hasArray()) {
            int length = directBuf.readableBytes();
            byte[] array = new byte[length];
            // 把数据读取到堆内存array中，再进行Java处理(无法直接获取内部数组，需要从直接内存拷贝到堆内存中)
            directBuf.getBytes(directBuf.readerIndex(), array);
            LOGGER.info(new String(array, StandardCharsets.UTF_8));
        }
        // 释放
        directBuf.release();

        // 默认创建堆内存缓冲区
        ByteBuf buffer = Unpooled.buffer();
    }
}
